import jwt,time   #导入jwt库，这是用于生成和验证JWT的Python库
from django.conf import settings #从setting中使用Django自带的密钥SECRET_KEY
from django.contrib.auth import get_user_model
from rest_framework.authentication import BaseAuthentication,get_authorization_header
from rest_framework import exceptions
from .models import OAUser
from jwt.exceptions import ExpiredSignatureError


#生成JWT
def generate_jwt(user): #接收一个用户对象作为参数，通常是从Django的User模型中获取的
    timestamp = time.time() + 60*60*24*15 #生成过期时间戳，计算当前时间戳加上7天的时间
    token = jwt.encode({"userid":user.uid,"exp":timestamp},key=settings.SECRET_KEY,algorithm='HS256')
        #生成JWT 用户的唯一标识符，通常是ID   过期时间         用于签名JWT的密钥            指定用于签名JWT的算法
    #print(token)
    return token

class UserTokenAuthentication(BaseAuthentication):
    def authenticate(self, request): #这个request是rest_framework.request.Request对象
        return request._request.user,request._request.auth  #返回请求对象中已有的用户和认证信息，传递给视图函数读取


#校验jwt
class JWTAuthentication(BaseAuthentication):
    """
    请求头中：
        Authorization: JWT 401f7ac837da42b97f613d789819ff93537bee6a
    """

    keyword = 'JWT'


    def authenticate(self, request):
        #从请求头中获取authorization

        auth = get_authorization_header(request).split() #从请求头中提取 Authorization 字段
        #auth:['JWT','401f7ac837da42b97f613d789819ff93537bee6a']
        if not auth or auth[0].lower() != self.keyword.lower().encode():
            #检查请求头中是否包含 Authorization 字段，并且该字段是否以 JWT 开头
            return None

        if len(auth) == 1:
            msg = '不可用的JWT请求头!'
            raise exceptions.AuthenticationFailed(msg)
        elif len(auth) > 2:
            msg = "不可用的JWT请求头!中间不应存在空格！"
            raise exceptions.AuthenticationFailed(msg)

        try: #进行解码
            jwt_token = auth[1]
            jwt_info = jwt.decode(auth[1],key=self.keyword.encode(),algorithms=['HS256'])
            #                              key和算法必须和加密的一致
            userid = jwt_info.get("userid")  #从解码后的 JWT 信息中提取 "userid" 键对应的值
            try:
                #绑定当前user到request对象上
                user = OAUser.objects.get(pk=userid) #使用用户 ID 从数据库中获取 OAUser 模型对象
                setattr(request,'user',user)
                return user,jwt_token
            except Exception :
                msg = "用户不存在！"
                raise exceptions.AuthenticationFailed(msg)
        # except UnicodeError:
        #     msg = '解码错误!'
        #     raise exceptions.AuthenticationFailed(msg)
        # except jwt.ExpiredSignatureError:
        #     msg = "已过期！"
        #     raise exceptions.AuthenticationFailed(msg)
        except ExpiredSignatureError:
            msg = 'JWT Token已过期！'
            raise exceptions.AuthenticationFailed(msg)